package cn.edu.xmu.oomall.liquidation.controller;

import cn.edu.xmu.oomall.core.model.VoObject;
import cn.edu.xmu.oomall.core.util.Common;
import cn.edu.xmu.oomall.core.util.JacksonUtil;
import cn.edu.xmu.oomall.core.util.ReturnNo;
import cn.edu.xmu.oomall.core.util.ReturnObject;
import cn.edu.xmu.oomall.liquidation.model.bo.StartInfo;
import cn.edu.xmu.oomall.liquidation.model.vo.StartInfoVo;
import cn.edu.xmu.oomall.liquidation.service.LiquidationService;
import cn.edu.xmu.privilegegateway.annotation.aop.Audit;
import cn.edu.xmu.privilegegateway.annotation.aop.LoginUser;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;

import static cn.edu.xmu.privilegegateway.annotation.util.Common.cloneVo;

/**
 * @author liuhezhao
 * @version 2021/12/4 10:55
 * @package_name cn.edu.xmu.oomall.liquidation.Controller
 * @project_name oomall
 * @product_name IntelliJ IDEA
 * @description
 */


@RefreshScope
@RestController
@RequestMapping(value = "", produces = "application/json;charset=UTF-8")
public class LiquidationController {
    @Autowired
    private HttpServletResponse httpServletResponse;

    @Autowired
    private LiquidationService liquidationService;

    @GetMapping(value = "/liquidation/states")
    public Object getLiquidationState() {
        ReturnObject<List<Map<String, Object>>> returnObject = liquidationService.getLiquidationState();
        return Common.decorateReturnObject(returnObject);
    }

    @Audit
    @GetMapping(value = "/shops/{shopId}/liquidation")
    public Object getLiquidatedList(@PathVariable("shopId") Long shopId,
                                    @RequestParam(value = "beginTime",required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime beginTime,
                                    @RequestParam(value = "endTime",required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime endTime,
                                    @RequestParam(required = false) Byte state,
                                    @RequestParam(required = false, defaultValue = "1") Integer page,
                                    @RequestParam(required = false, defaultValue = "5") Integer pageSize) {

        LocalDateTime begin = null;
        LocalDateTime end = null;
        if (beginTime != null && endTime != null) {
            if (beginTime.isAfter(endTime)) {
                return Common.decorateReturnObject(new ReturnObject<>(ReturnNo.LATE_BEGINTIME));
            }
            begin = beginTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
            end = endTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
        }
        if (shopId >= 0) {
            ReturnObject<PageInfo<VoObject>> returnObject = liquidationService.getLiquidatedList(shopId, begin, end, state, page, pageSize);
            return Common.getPageRetObject(returnObject);
        }

        return Common.decorateReturnObject(new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST));
    }

    @Audit
    @GetMapping(value = "/shops/{shopId}/liquidation/{id}")
    public Object getLiquidatedListDetail(@PathVariable("shopId") Long shopId,
                                          @PathVariable("id") Long id) {
        if (shopId >= 0 && id >= 0) {
            ReturnObject<Object> returnObject = liquidationService.getLiquidatedListDetail(shopId, id);
            return Common.decorateReturnObject(returnObject);
        }
        return Common.decorateReturnObject(new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST));
    }

    @Audit
    @GetMapping(value = "/shops/{shopId}/revenue")
    public Object getRevenue(@PathVariable("shopId") Long shopId,
                             @RequestParam(required = false) Long orderId,
                             @RequestParam(required = false) Long productId,
                             @RequestParam(required = false) Long liquidationId,
                             @RequestParam(required = false, defaultValue = "1") Integer page,
                             @RequestParam(required = false, defaultValue = "5") Integer pageSize) {
        if (shopId > 0) {
            ReturnObject<PageInfo<VoObject>> returnObject = liquidationService.getRevenue(shopId, orderId, productId, liquidationId, page, pageSize);
            return Common.getPageRetObject(returnObject);
        }
        return Common.decorateReturnObject(new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST));
    }

    @Audit
    @GetMapping(value = "/shops/{shopId}/expenditure")
    public Object getExpenditure(@PathVariable("shopId") Long shopId,
                                 @RequestParam(required = false) Long orderId,
                                 @RequestParam(required = false) Long productId,
                                 @RequestParam(required = false) Long liquidationId,
                                 @RequestParam(required = false, defaultValue = "1") Integer page,
                                 @RequestParam(required = false, defaultValue = "5") Integer pageSize) {
        if (shopId > 0) {
            ReturnObject<PageInfo<VoObject>> returnObject = liquidationService.getExpenditure(shopId, orderId, productId, liquidationId, page, pageSize);
            return Common.getPageRetObject(returnObject);
        }
        return Common.decorateReturnObject(new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST));
    }

    @Audit
    @GetMapping(value = "/shops/{shopId}/expenditure/{id}/revenue")
    public Object getRevenueFromExpenditure(@PathVariable("shopId") Long shopId,
                                            @PathVariable("id") Long id) {
        if (shopId > 0 && id > 0) {
            ReturnObject<Object> returnObject = liquidationService.getRevenueFromExpenditure(shopId, id);
            return Common.decorateReturnObject(returnObject);
        }
        return Common.decorateReturnObject(new ReturnObject(ReturnNo.RESOURCE_ID_NOTEXIST));
    }

    @Audit
    @GetMapping(value = "/pointrecords/revenue")
    public Object getPointRecordsRevenue(@RequestParam(value = "beginTime",required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime beginTime,
                                         @RequestParam(value = "endTime",required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime endTime,
                                      @RequestParam(required = false, defaultValue = "1") Integer page,
                                      @RequestParam(required = false, defaultValue = "5") Integer pageSize) {
        LocalDateTime begin = null;
        LocalDateTime end = null;
        if (beginTime != null && endTime != null) {
            if (beginTime.isAfter(endTime)) {
                return Common.decorateReturnObject(new ReturnObject<>(ReturnNo.LATE_BEGINTIME));
            }
            begin = beginTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
            end = endTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
        }
        ReturnObject<PageInfo<VoObject>> returnObject = liquidationService.getPointRecordsRevenue(begin, end, page, pageSize);
        return Common.getPageRetObject(returnObject);
    }

    @Audit
    @GetMapping(value = "/pointrecords/expenditure")
    public Object getPointRecordsExpenditure(@RequestParam(value = "beginTime",required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime beginTime,
                                             @RequestParam(value = "endTime",required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime endTime,
                                  @RequestParam(required = false, defaultValue = "1") Integer page,
                                  @RequestParam(required = false, defaultValue = "5") Integer pageSize) {
        LocalDateTime begin = null;
        LocalDateTime end = null;
        if (beginTime != null && endTime != null) {
            if (beginTime.isAfter(endTime)) {
                return Common.decorateReturnObject(new ReturnObject<>(ReturnNo.LATE_BEGINTIME));
            }
            begin = beginTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
            end = endTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
        }
        ReturnObject<PageInfo<VoObject>> returnObject = liquidationService.getPointRecordsExpenditure(begin, end, page, pageSize);
        return Common.getPageRetObject(returnObject);
    }

    @Audit
    @PutMapping(value = "/shops/{shopId}/liquidation/start")
    public Object startLiquidate(@PathVariable("shopId") Long shopId, @LoginUser Long adminId, @LoginUser String adminName, @Validated @RequestBody StartInfoVo startInfoVo, BindingResult bindingResult) {
        if (shopId != 0) {
            return new ReturnObject<>(ReturnNo.RESOURCE_ID_OUTSCOPE);
        }
        var res = Common.processFieldErrors(bindingResult, httpServletResponse);
        if (res != null) {
            return res;
        }
        ReturnObject returnObject = liquidationService.startLiquidate(startInfoVo, adminId, adminName);
        return Common.decorateReturnObject(returnObject);
    }
}
